<?php
if(!defined('mcz_BENCHMARK'))
{
	define('mcz_BENCHMARK', true);
}
final class mcz_Benchmark
{
	public static $marks = array();

	/*
	   Method: Start
	   Set a benchmark start point.
	*/
	public static function start($name)
	{
		if(!mcz_BENCHMARK)
		{
			return false;
		}
		if (!isset(self::$marks[$name]))
		{
			self::$marks[$name] = array
			(
				'start'        => microtime(true),
				'stop'         => false,
				'memory_start' => function_exists('memory_get_usage') ? memory_get_usage() : 0,
				'memory_stop'  => false
			);
		}
		return true;
	}

	/*
	   Method: stop
	   Set a benchmark stop point.
	*/
	public static function stop($name)
	{
		if(!mcz_BENCHMARK)
		{
			return false;
		}
		if (isset(self::$marks[$name]))
		{
			self::$marks[$name]['stop'] = microtime(true);
			self::$marks[$name]['memory_stop'] = function_exists('memory_get_usage') ? memory_get_usage() : 0;
		}
		return true;
	}

	/*
	   Method: get
	   Get the elapsed time between a start and stop of a mark name, TRUE for all.
	*/
	public static function get($name, $decimals = 4)
	{
		if(!mcz_BENCHMARK)
		{
			return false;
		}
		if ($name === true)
		{
			$times = array();

			foreach(array_keys(self::$marks) as $name)
			{
				$times[$name] = self::get($name, $decimals);
			}

			return $times;
		}

		if (!isset(self::$marks[$name]))
		{
			return false;
		}

		if (self::$marks[$name]['stop'] === false)
		{
			self::stop($name);
		}

		return array
		(
			'time'   => number_format(self::$marks[$name]['stop'] - self::$marks[$name]['start'], $decimals),
			'memory' => self::convert_size(self::$marks[$name]['memory_stop'] - self::$marks[$name]['memory_start'])
		);
	}

	public static function convert_size($num)
	{
		if ($num >= 1073741824)
		{
			$num = round($num / 1073741824 * 100) / 100 .' gb';
		}
		else if ($num >= 1048576)
		{
			$num = round($num / 1048576 * 100) / 100 .' mb';
		}
		else if ($num >= 1024)
		{
			$num = round($num / 1024 * 100) / 100 .' kb';
		}
		else
		{
			$num .= ' b';
		}
		return $num;
	}

	public static function htmlReport()
	{
		if(!mcz_BENCHMARK)
		{
			return '';
		}
		$html = '<ol>';
		foreach(self::get(true) as $key => $val)
		{
			$html .= '<li><strong>' . htmlspecialchars($key) . '</strong><br/>time: ' . $val['time'] . '<br/>memory: ' . $val['memory'] . '</li>';
		}
		return $html . '</ol>';
	}

	public static function cliReport()
	{
		$output = '';
		if(!mcz_BENCHMARK)
		{
			return $output;
		}
		$points = self::get(true);
		if(!empty($points))
		{
			$output .= "\n#### Benchmark ####\n";
			foreach($points as $key => $val)
			{
				$output .= "\n[ " . $key . " ]\n        time: " . $val['time'] . "\n        memory: " . $val['memory'] . "\n";
			}
		}
		return $output;
	}

}
